package com.gitee.zycra.future.job.service;

import com.gitee.zycra.future.job.common.bo.CommonResult;
import com.gitee.zycra.future.job.common.bo.PageQuery;
import com.gitee.zycra.future.job.common.config.EncryptConfig;
import com.gitee.zycra.future.job.common.model.JobUser;
import com.gitee.zycra.future.job.common.param.AddUserParam;
import com.gitee.zycra.future.job.common.param.PageQueryUserParam;
import com.gitee.zycra.future.job.common.param.UpdateUserParam;
import com.gitee.zycra.future.job.common.param.UserLoginParam;
import com.gitee.zycra.future.job.common.util.AESUtil;
import com.gitee.zycra.future.job.common.util.CaptchaUtil;
import com.gitee.zycra.future.job.common.util.DateUtil;
import com.gitee.zycra.future.job.common.vo.JobUserVO;
import com.gitee.zycra.future.job.common.vo.UserLoginVO;
import com.gitee.zycra.future.job.manager.JobUserManager;
import com.gitee.zycra.jdbc.model.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author zycra
 */
@Slf4j
@Service
public class JobUserService {

    @Autowired
    private JobUserManager jobUserManager;

    @Autowired
    private EncryptConfig encryptConfig;

    /**
     * 验证码宽度
     */
    private static final int CAPTCHA_WIDTH = 160;

    /**
     * 验证码高度
     */
    private static final int CAPTCHA_HEIGHT = 40;

    /**
     * toekn过期时间
     */
    private static final long TOKEN_EXPIRE_MINUTES = 30L;

    /**
     * 插入
     *
     * @param addUserParam 调度时间配置对象
     * @return 插入条数
     */
    public int insertJobUser(AddUserParam addUserParam) {
        return jobUserManager.insertJobUser(AddUserParam.convertToJobUser(addUserParam));
    }

    /**
     * 禁用/启用
     *
     * @param id       用户ID
     * @param enabled 是否启用
     * @return 影响条数
     */
    public int changeJobUser(Long id, Boolean enabled) {
        return jobUserManager.changeJobUser(id, enabled);
    }

    /**
     * 更新
     *
     * @param param 用户对象
     * @return 更新条数
     */
    public int updateJobUser(UpdateUserParam param) {
        return jobUserManager.updateJobUser(UpdateUserParam.convertToJobUser(param));
    }

    /**
     * 根据条件查询
     *
     * @param pageQuery 查询条件
     * @return 查询到的数据
     */
    public PageResult<JobUserVO> selectJobUserForPage(PageQuery<PageQueryUserParam> pageQuery) {
        PageResult<JobUser> result = jobUserManager.selectJobUserForPage(pageQuery);
        List<JobUser> data = result.getData();
        List<JobUserVO> voList = new ArrayList<>();
        for (JobUser jobUser : data) {
            voList.add(JobUserVO.buildJobUserVO(jobUser));
        }
        return new PageResult<>(result.getPage(), result.getTotal(), voList);
    }

    /**
     * 登录
     *
     * @param userLoginParam 登录参数
     * @return 登录结果对象
     */
    public CommonResult<UserLoginVO> login(UserLoginParam userLoginParam) {
        String captchaToken = userLoginParam.getCaptchaToken();
        if (captchaToken != null) {
            captchaToken = AESUtil.decrypt(captchaToken, encryptConfig.getTokenKey());
            if (captchaToken == null || !captchaToken.equalsIgnoreCase(userLoginParam.getCaptcha())) {
                log.warn("验证码校验失败, userLoginParam={}", userLoginParam);
                return getFailedVO("验证码校验失败");
            }
        }
        JobUser jobUser = jobUserManager.selectJobUserByUsername(userLoginParam.getUsername());
        if (jobUser == null) {
            log.warn("用户不存在, userLoginParam={}", userLoginParam);
            return getFailedVO("用户不存在");
        }
        LocalDateTime lastLoginTime = jobUser.getLastLoginTime();
        LocalDateTime now = DateUtil.getNowLocalDateTime();
        jobUserManager.updateJobUser(new JobUser().setId(jobUser.getId()).setLastLoginTime(DateUtil.getNowLocalDateTime()));
        if (captchaToken == null && lastLoginTime.isAfter(now.minusMinutes(1L))) {
            log.warn("未输入验证码, userLoginParam={}", userLoginParam);
            return getFailedVO("请输入验证码");
        }
        if (lastLoginTime.isAfter(now.minusSeconds(1L))) {
            log.warn("登录频繁, userLoginParam={}", userLoginParam);
            return getFailedVO("登录频繁,请稍后重试");
        }
        boolean success = BCrypt.checkpw(userLoginParam.getPwd(), jobUser.getPwd());
        if (!success) {
            log.warn("用户名或密码错误, userLoginParam={}", userLoginParam);
            return getFailedVO("用户名或密码错误");
        }
        Long expireTime = DateUtil.convertToTimestamp(DateUtil.getNowLocalDateTime().plusMinutes(TOKEN_EXPIRE_MINUTES));
        String token = AESUtil.encrypt(jobUser.getId().toString() + "," + jobUser.getAuth() + "," + jobUser.getUsername() + "," + expireTime,
                encryptConfig.getTokenKey());
        return CommonResult.success("登录成功", new UserLoginVO().setToken(token));
    }

    private CommonResult<UserLoginVO> getFailedVO(String message) {
        CaptchaUtil.Captcha captcha = CaptchaUtil.createCaptcha(CAPTCHA_WIDTH, CAPTCHA_HEIGHT);
        return CommonResult.failed(message, new UserLoginVO()
                .setCaptchaToken(AESUtil.encrypt(captcha.getCaptchaCode(), encryptConfig.getTokenKey()))
                .setCaptchaImage(captcha.getCaptchaImage()));
    }

    /**
     * 获取验证码
     *
     * @return 验证码
     */
    public CommonResult<UserLoginVO> getCaptcha() {
        CaptchaUtil.Captcha captcha = CaptchaUtil.createCaptcha(CAPTCHA_WIDTH, CAPTCHA_HEIGHT);
        return CommonResult.success(new UserLoginVO()
                .setCaptchaToken(AESUtil.encrypt(captcha.getCaptchaCode(), encryptConfig.getTokenKey()))
                .setCaptchaImage(captcha.getCaptchaImage()));
    }
}
